/* api */
import { workWechatSign } from '@src/api/WechatApi'
/* class */
import BasePlatform from '@src/platform/extension/base'
/* types */
import WorkWeixinJsApi, { ConfigOptions, WorkWeixinAgentConfigOptions } from '@model/types/WorkWeixinJsApi'
/* model */
import { WorkWeixinSignData, WorkWeixinSignResult } from '@model/param/out/WX'
import { getRootWindow, isWorkWeiXin } from '@src/util/platform'
/* util */
import Log from '@src/util/log.ts'
import { parse } from '@src/util/querystring'
import { getRootWindowInitData } from '@src/util/window'

const defaultCode: string = 'web'
const rootWindow = getRootWindow(window)

function getLocationQYWXCode(): string {
	return parse(window.location.search).code || defaultCode
}

function getWindowQYWXCode(): string {
	return rootWindow.qywxCode || ''
}

function setQYWXCode(code: string) {
	rootWindow.qywxCode = code
}

function normalizePath(href: string, code: string) {
	return `${href}?code=${code}`
}

function getLocationHref() {
	let href = window.location.href
  let suffix = 'ltd/'
	let suffixIndex = href.indexOf(suffix)
  
	return href.substr(0, suffixIndex + suffix.length)
}

function getSignedUrl() {
	// 无企业微信操作码
	if (!getWindowQYWXCode()) {
		setQYWXCode(getLocationQYWXCode())
		return window.location.href
	}
  
    const qywxCode: string = getWindowQYWXCode()
	const locationHref: string = getLocationHref()
	if (qywxCode == defaultCode) {
		return locationHref
	}
  
	return normalizePath(locationHref, qywxCode)
}

class WXPlatformChat {
	// 打开会话
	openEnterpriseChat(
		userIds?: string, 
		externalUserIds?: string,
		groupName?: string,
		chatId?: string,
	): Promise<string> {
    
		Log.succ(Log.Start, `WXPlatformChat -> ${this.openEnterpriseChat.name}`)
		Log.info(externalUserIds, 'externalUserIds', this.openEnterpriseChat.name)
    
		return (
			new Promise((resolve, reject) => {
				rootWindow.wx.openEnterpriseChat({
					userIds: userIds || '',
					externalUserIds: externalUserIds || '',
					groupName: groupName || '',
					chatId: chatId || '',
					success(res: { chatId: string }) {
            
						Log.info(res, 'res', 'openEnterpriseChat -> success')
            
						// 返回当前群聊ID，仅当使用agentConfig注入该接口权限时才返回chatId
						resolve(res?.chatId || '')
					},
					fail(res: { errMsg: string }) {
            
						Log.info(res, 'res', 'openEnterpriseChat -> fail')
            
						if(res.errMsg.indexOf('function not exist') > -1){
							alert('企业微信版本过低请升级')
						}
            
						reject()
					}
				})
			})
		)
	}
  
  // 打开会话(单人聊天)
	openEnterpriseChatForSignle(externalUserIds: string) {
    Log.succ(Log.Start, `WXPlatformChat -> ${this.openEnterpriseChatForSignle.name}`)
		Log.info(externalUserIds, 'externalUserIds', this.openEnterpriseChatForSignle.name)
    
		return this.openEnterpriseChat('', externalUserIds)
	}
  
	// 打开会话(群组聊天)
	openEnterpriseChatForGroup() {
		Log.succ(Log.Start, `WXPlatformChat -> ${this.openEnterpriseChatForGroup.name}`)
	}
}

class WXPlatform {
  
  chat = new WXPlatformChat()
	
  injectAuth(_config: WorkWeixinSignData): Promise<void> {
    
		Log.succ(Log.Start, `WXPlatformChat -> ${this.injectAuth.name}`)
		Log.info(_config, '_config', this.injectAuth.name)
    
		let config = rootWindow.wxConfig = _config
		let jsApiList = [
			'checkJsApi',
			'chooseImage',
			'uploadImage',
			'previewImage',
			'downloadImage',
			'scanQRCode',
			'getLocation',
			'openLocation',
			'startRecord',
			'stopRecord',
			'onVoiceRecordEnd',
			'playVoice',
			'pauseVoice',
			'stopVoice',
			'onVoicePlayEnd',
			'uploadVoice',
			'downloadVoice',
			'translateVoice',
			'openDefaultBrowser',
			'onHistoryBack',
			'closeWindow',
			'hideOptionMenu',
			'openEnterpriseChat',
			'setClipboardData',
			'navigateToAddCustomer',
			'selectExternalContact',
			'getCurExternalContact',
			'getContext',
			'sendChatMessage',
			'selectEnterpriseContact'
		];
		
		let authConfig = {
			beta: true, // 必须这么写，否则wx.invoke调用形式的jsapi会有问题
			debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来，若要查看传入的参数，可以在pc端打开，参数信息会通过log打出，仅在pc端时才会打印。
			appId: config.appId, 
			timestamp: config.timestamp,
			nonceStr: config.nonceStr,
			signature: config.signature,
			jsApiList 
		}
    
		let agentConfig: WorkWeixinAgentConfigOptions = {
			timestamp: config.timestamp, // 必填，生成签名的时间戳
			nonceStr: config.nonceStr, // 必填，生成签名的随机串
			signature: config.sdkSignature, // 必填，签名，见附录-JS-SDK使用权限签名算法
			jsApiList,
			corpid: config.appId, // 必填，企业微信的corpid，必须与当前登录的企业一致
			agentid: config.agentId, // 必填，企业微信的应用id （e.g. 1000247）
		}
    
		Log.info(authConfig, 'authConfig', this.injectAuth.name)
		Log.info(agentConfig, 'agentConfig', this.injectAuth.name)
		
		if (isWorkWeiXin()) {
			return this.injectAuthWorkWeiXin(authConfig, agentConfig)
		}
    
		return this.injectAuthByThirdPartyBrowser(authConfig, agentConfig)
	}
  
	/** 
	 * @description 企业微信环境注入权限
	 * @see https://developer.work.weixin.qq.com/document/path/90514
	 * @see https://developer.work.weixin.qq.com/document/path/94313
	 * @param {ConfigOptions} authConfig 权限验证配置
	 * @param {WorkWeixinAgentConfigOptions} agentConfig 第三方应用的身份信息
	 * @returns {Promise<void>}
	*/
	injectAuthWorkWeiXin(authConfig: ConfigOptions, agentConfig: WorkWeixinAgentConfigOptions): Promise<void> {
		return (
			new Promise((resolve, reject) => {
				
				rootWindow.wx.config(authConfig)
				
				rootWindow.wx.ready(function () {
					Log.succ(Log.Start, `rootWindow.wx.ready -> ready`)
					
					rootWindow.wx?.agentConfig({
						...agentConfig,
						success(res: any) {
							Log.info(res, 'res', 'agentConfig -> success')
							resolve()
						},
						fail(res: any) {
							
							Log.error(res, `agentConfig -> fail`)
							Log.info(res, 'res', 'agentConfig -> fail')
							
							if(res.errMsg.indexOf('function not exist') > -1){
								alert('企业微信版本过低请升级')
							}
							
							reject(res)
						}
					})
          
					resolve()
				})
				
				rootWindow.wx.error(error => {
					Log.error(error, `rootWindow.wx.error -> error`)
					reject(error)
				})
				
			})
		)
	}
  
	/** 
	 * @description 第三方浏览器环境注入权限
	 * @see https://developer.work.weixin.qq.com/document/path/94313
	 * @param {WorkWeixinAgentConfigOptions} agentConfig 第三方应用的身份信息
 	 * @returns {Promise<void>}
	*/
	injectAuthByThirdPartyBrowser(authConfig: ConfigOptions, agentConfig: WorkWeixinAgentConfigOptions): Promise<void> {
		return new Promise((resolve, reject) => {
			
			rootWindow.wx.config(authConfig)
			
			rootWindow.wx.ready(function () {
				Log.succ(Log.Start, `rootWindow.wx.ready -> ready`)
			})
			
			rootWindow.wx?.agentConfig({
				...agentConfig,
				success(res: any) {
					Log.info(res, 'res', 'agentConfig -> success')
					resolve()
				},
				fail(res: any) {
					
					Log.error(res, `agentConfig -> fail`)
					Log.info(res, 'res', 'agentConfig -> fail')
					
					if(res.errMsg.indexOf('function not exist') > -1){
						alert('企业微信版本过低请升级')
					}
					
					reject(res)
				}
			})
			
			rootWindow.wx.error(error => {
				Log.error(error, `rootWindow.wx.error -> error`)
				reject(error)
			})
			
		})
	}
  
	async sign(): Promise<void> {
		const rootWindowInitData = getRootWindowInitData()
    let tenantType = rootWindowInitData.tenantType || 0
		if(tenantType != 2) return Promise.resolve()

		Log.succ(Log.Start, `WXPlatformChat -> ${this.sign.name}`)
    
		try {
			// 需要签名的地址
			let signedUrl: string = getSignedUrl()
			// 签名后得到的结果信息
			let result: WorkWeixinSignResult = await workWechatSign({ url: signedUrl })
			let data: WorkWeixinSignData | null | undefined = result?.data
      
			Log.info(data, 'data', this.sign.name)
      
      if (!data) {
				return Promise.resolve()
			}
      
			return (
				new Promise((resolve, reject) => {
					this.injectAuth(data as WorkWeixinSignData)
						.then(() => {
							resolve()
						})
						.catch(err => {
							console.log(err)
							resolve()
						})
				})
			)
      
		} catch (error) {
			return Promise.resolve()
		}
	}
	
}

export default WXPlatform
